Skip to main content

--

Brotli

Overview

Brotli is a lossless compression format and algorithm commonly used for HTTP content encoding (Content-Encoding: br) and for compressing files on disk. It typically achieves smaller sizes than gzip on web assets (HTML, CSS, JavaScript) while remaining widely supported by modern clients.

History

  • Brotli originated at Google as a compression format optimized for web use, with early adoption driven by browser and web platform needs.
  • It was later standardized for HTTP as an IETF specification (RFC 7932), enabling interoperable use across servers, CDNs, and browsers.

Adoption

Brotli is commonly used in:

  • Web servers and CDNs to compress text-based responses and static assets
  • Build pipelines to precompress .js, .css, and .svg files for efficient delivery
  • APIs and web apps that negotiate compression via Accept-Encoding

Maintainer

Maintained by the Brotli open-source community (with an original reference implementation developed at Google).

Best when to use

  • Serving static web assets where smaller transfer size improves page load performance
  • Precompressing build outputs for predictable, cache-friendly delivery
  • Compressing large text-heavy files (logs, JSON exports) for storage and transport

Not suitable when

  • You cannot provide a fallback (gzip/identity) for older clients or constrained intermediaries
  • You plan to compress dynamic responses containing secrets mixed with attacker-controlled input (risk of compression side-channels)
  • CPU budget is tight and you intend to use maximum compression levels on-the-fly

Compatibility notes

  • HTTP negotiation depends on the client’s Accept-Encoding. Servers should support fallback to gzip (and optionally identity) for broad compatibility.

  • Many server stacks can do either dynamic compression (on each request) or static precompression (serving .br files). Static precompression is usually safer for CPU predictability.

  • Tooling differences:

    • Some systems ship a brotli CLI.
    • Some environments use library bindings instead of the CLI (for example, in application runtimes).
Operational default

Prefer static precompression for immutable assets and use moderate quality levels for good size/CPU balance.

Concepts and how it works

Brotli compression combines:

  • LZ77-style back-references (reusing repeated byte sequences)
  • Entropy coding (Huffman-like coding)
  • Context modeling tuned for common web content patterns

In HTTP, Brotli is typically used like this:

Key operational points:

  • Compression level affects CPU time much more than decompression time.
  • Static assets benefit most because they are compressed once and served many times.
  • Always send Vary: Accept-Encoding when serving different encodings for the same URL.

Installation

Verify first (read-only)

brotli --version
brotli --help

Install via package manager

sudo apt update
sudo apt install brotli

Common commands and options

Basic syntax

brotli [options] input_file

By default, the CLI writes input_file.br next to the input (unless you specify -o).

Inspect before changing anything (read-only)

Check what files exist and their sizes:

ls -lh input_file input_file.br 2>/dev/null || true

Compress a file

Create input_file.br (default behavior):

brotli input_file

Specify output path:

brotli -o out/input_file.br input_file

Write to stdout (useful in pipelines):

brotli -c input_file > input_file.br

Decompress a file

Decompress to a new output file:

brotli -d -o input_file input_file.br

Decompress to stdout:

brotli -d -c input_file.br > input_file
Overwrite risk

If you use -f (force), the CLI may overwrite output files. Prefer writing to a new path and verifying the result before replacing any originals.

Important flags (practical)

FlagMeaningTypical useNotes
--
-dDecompressbrotli -d input.brInput is usually a .br file
-o <file>Output filebrotli -o out.br inAvoids accidental overwrite
-cOutput to stdoutbrotli -c in > out.brGood for pipelines
-fForce overwritebrotli -f -o out.br inUse carefully
-q <0..11>Quality levelbrotli -q 6 inHigher is smaller but slower to compress
-w <lgwin>Window size parameterbrotli -w 22 inAdvanced tuning; affects memory and ratio
-m <mode>Content modebrotli -m text inCommon: generic, text, font
Practical defaults
  • For static web assets, start with -q 6 to -q 9.
  • Reserve -q 11 for offline compression where CPU time is acceptable.

Practical use cases

Precompress static web assets

Precompress build outputs into a separate directory:

mkdir -p dist-br
find dist -type f \( -name "*.js" -o -name "*.css" -o -name "*.html" -o -name "*.svg" -o -name "*.json" \) \
-print0 | xargs -0 -I{} sh -c 'brotli -q 9 -o "dist-br/{}.br" "{}"'

Verify a few outputs:

ls -lh dist/app.js dist-br/dist/app.js.br 2>/dev/null || true

Serve .br assets correctly

To serve precompressed assets, the server must:

  • Return Content-Encoding: br for the .br representation
  • Return the original Content-Type for the underlying file type
  • Add Vary: Accept-Encoding
  • Fall back to gzip or identity when the client does not accept br
Server configuration

Configuration details vary by server and framework. Use your server’s official documentation for “static Brotli” or “precompressed assets” and validate headers with curl -I.

Validate HTTP negotiation (read-only)

Check response headers (server must already be configured):

curl -I -H 'Accept-Encoding: br' https://example.com/app.js

Look for:

  • Content-Encoding: br
  • Vary: Accept-Encoding

Troubleshooting

Output is larger than gzip

  • Use Brotli primarily for text-based content (.html, .css, .js, .svg, .json).
  • For already-compressed formats (.jpg, .png, .mp4, .zip), compression often provides little benefit and may waste CPU.

Recommended check:

ls -lh file.gz file.br 2>/dev/null || true

Browser downloads a .br file instead of using it

This usually indicates the server is serving the .br file as a normal download, without the required header.

What to verify:

  • The response for the original URL includes Content-Encoding: br
  • The Content-Type matches the original asset type (for example, JavaScript)
  • Vary: Accept-Encoding is present

Read-only header check:

curl -I -H 'Accept-Encoding: br' https://example.com/app.js

Decompression fails

Common causes:

  • Corrupted or truncated .br file
  • Mismatched toolchain or partial downloads

Try decompressing to stdout and checking exit status:

brotli -d -c input.br > /dev/null
echo $?

Security notes

Compression side-channels

Avoid compressing responses that combine secrets (tokens, session identifiers) with attacker-controlled input. This is a general risk across HTTP compression methods (Brotli/gzip/deflate) and is especially relevant for dynamic HTML and reflected content.

Operational safeguards:

  • Prefer static precompression for immutable public assets.
  • Apply resource limits for untrusted decompression paths (application-level limits, timeouts, file size caps).
  • Avoid decompressing untrusted data without limits; decompression bombs can exhaust memory or disk.

Quick reference

TaskCommand
---
Show version/helpbrotli --version / brotli --help
Compress (default output)brotli input_file
Compress with qualitybrotli -q 9 -o input_file.br input_file
Compress to stdoutbrotli -c input_file > input_file.br
Decompress to filebrotli -d -o input_file input_file.br
Decompress to stdoutbrotli -d -c input_file.br > input_file
Force overwrite (use carefully)brotli -f -o out.br in
Validate HTTP headerscurl -I -H 'Accept-Encoding: br' https://example.com/file.js